package net.hkbn.prov.helper;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.io.DocumentSource;

public class EmailTemplateHelper {
	private String xslEmailTemplate = null;
	private Map eleMap = new HashMap();

	private Map rowsMap = new HashMap();

	public String getXslEmailTemplate() {
		return xslEmailTemplate;
	}

	public void setXslEmailTemplate(String xslEmailTemplate) {
		this.xslEmailTemplate = xslEmailTemplate;
	}

	public void addElement(String key, String value) {
		eleMap.put(key, value);
	}
	
	/**
	 * Release HashMap resource to avoid memory leap
	 */
	public void clearRowsElement() {
		this.rowsMap.clear();
	}
	 

	/**
	 * Add one row contents to a table
	 * 
	 * @param table
	 *          table's name
	 * @param rowMap
	 *          row content by key and value
	 */
	public void addRowElement(String table, Map rowMap) {
		if (rowMap != null && rowMap.size() > 0) {
			List rowsList = null;
			if (!rowsMap.containsKey(table)) {
				rowsList = new ArrayList();
				rowsMap.put(table, rowsList);
			} else {
				rowsList = (List) rowsMap.get(table);
			}
			rowsList.add(rowMap);
		}
	}

	public String transEmailTemplate() {
		String result = "";
		try {
			Document xmlDocument = DocumentHelper.createDocument();
			Element eTemplate = xmlDocument.addElement("Template");

			String eleKey = null;
			String eleVal = null;
			if (eleMap.size() > 0) {
				Iterator keyIter = eleMap.keySet().iterator();
				while (keyIter.hasNext()) {
					eleKey = (String) keyIter.next();
					eleVal = (String) eleMap.get(eleKey);
					if (eleVal == null) {
						eleVal = "";
					}
					Element element = eTemplate.addElement(eleKey);
					element.setText(eleVal);
				}
			}

			String rowsKey = null;
			List rowsList = null;
			if (rowsMap.size() > 0) {
				Iterator keyIter = rowsMap.keySet().iterator();
				while (keyIter.hasNext()) {
					rowsKey = (String) keyIter.next();
					rowsList = (List) rowsMap.get(rowsKey);
					Element eRows = eTemplate.addElement(rowsKey);
					Map rowMap = null;

					if (rowsList != null && rowsList.size() > 0) {
						for (int i = 0; i < rowsList.size(); i++) {
							rowMap = (Map) rowsList.get(i);
							Element eRow = eRows.addElement("row");

							if (rowMap != null && rowMap.size() > 0) {
								Iterator eleIter = rowMap.keySet().iterator();
								while (eleIter.hasNext()) {
									eleKey = (String) eleIter.next();

									Element eCell = eRow.addElement(eleKey);

									Object eleObject = rowMap.get(eleKey);

									if (eleObject != null) {
										if (eleObject.getClass().equals(ArrayList.class)) {
											List sList = (List) eleObject;
											if (sList != null && sList.size() > 0) {
												Map sRowM = null;
												for (int j = 0; j < sList.size(); j++) {
													Element esRow = eCell.addElement("srow");
													sRowM = (Map) sList.get(j);
													Iterator sEleIter = sRowM.keySet().iterator();
													while (sEleIter.hasNext()) {
														String sEleKey = (String) sEleIter.next();
														Element seCell = esRow.addElement(sEleKey);
														if (sRowM.get(sEleKey) != null) {
															seCell.setText(sRowM.get(sEleKey).toString());
														} else {
															seCell.setText("");
														}
													}
												}
											}
										} else {
											eleVal = eleObject.toString();
											eCell.setText(eleVal);
										}
									} else {
										eCell.setText("");
									}
								}
							}
						}
					}
				}
			}

			DocumentSource xmlSource = new DocumentSource(xmlDocument);
			
			// - load from class
			InputStream file = EmailTemplateHelper.class.getResourceAsStream(xslEmailTemplate);
			if (file == null) {
				file = new FileInputStream(xslEmailTemplate);
			}
			StreamSource xsltSource = new StreamSource(file);
			
			EmailTemplateHelper.class.getResourceAsStream(xslEmailTemplate);
			
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer(xsltSource);
			OutputStream outputStream = new ByteArrayOutputStream();
			StreamResult htmlResult = new StreamResult(outputStream);

			transformer.setOutputProperty("encoding", "UTF-8");
			transformer.transform(xmlSource, htmlResult);
			result = htmlResult.getOutputStream().toString();

			outputStream.flush();
		    outputStream.close();
	
		} catch (TransformerConfigurationException e) {
			e.printStackTrace();
		} catch (TransformerFactoryConfigurationError e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (TransformerException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			eleMap.clear();
			rowsMap.clear();
		}

		return result;
	}
}
